//+------------------------------------------------------------------+
//|                        RangeFilter_Signal_Styled_V3.mq5          |
//|   Range Filter with Solid Arrows, Clean Buffers (by ChatGPT GPT-5)|
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_plots   5

//---- 主滤波线
#property indicator_label1  "Filter"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepSkyBlue
#property indicator_width1  3

//---- 上下边界
#property indicator_label2  "High Band"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrLime
#property indicator_style2  STYLE_DOT

#property indicator_label3  "Low Band"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrRed
#property indicator_style3  STYLE_DOT

//---- 买入信号箭头
#property indicator_label4  "BUY"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrAqua
#property indicator_width4  3

//---- 卖出信号箭头
#property indicator_label5  "SELL"
#property indicator_type5   DRAW_ARROW
#property indicator_color5  clrTomato
#property indicator_width5  3

//---- 输入参数
input int    Range_Period     = 20;
input double Range_Multiplier = 3.5;
input ENUM_APPLIED_PRICE Range_Source = PRICE_CLOSE;
input bool   Enable_Alert     = true;
input bool   Enable_DebugLog  = false;

//---- Buffers
double filtBuffer[];
double hiBandBuffer[];
double loBandBuffer[];
double buySignal[];
double sellSignal[];
double directionBuffer[];
double rangeBuffer[];

// 内部变量
bool firstRun = true;

//+------------------------------------------------------------------+
//| Range Size Function                                              |
//+------------------------------------------------------------------+
double RangeSize(const double &src[], int n, double qty, int i)
{
   if (i <= 1) return 0.0;
   double sum = 0.0;
   for(int j = i - n + 1; j <= i; j++)
   {
      if(j > 0)
         sum += fabs(src[j] - src[j - 1]);
   }
   double avrange = sum / n;
   return avrange * qty;
}

//+------------------------------------------------------------------+
//| Range Filter Function                                            |
//+------------------------------------------------------------------+
double RangeFilter(double x, double r)
{
   static double filt_val = 0.0;
   if(firstRun)
   {
      filt_val = x;
      firstRun = false;
   }

   if(x - r >= filt_val)
      filt_val = x - r;
   if(x + r <= filt_val)
      filt_val = x + r;

   return filt_val;
}

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   IndicatorSetString(INDICATOR_SHORTNAME, "Range Filter V3 (Solid Arrows)");

   // 分配缓冲区
   SetIndexBuffer(0, filtBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, hiBandBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, loBandBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, buySignal, INDICATOR_DATA);
   SetIndexBuffer(4, sellSignal, INDICATOR_DATA);
   SetIndexBuffer(5, directionBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(6, rangeBuffer, INDICATOR_CALCULATIONS);

   // 初始化为 EMPTY_VALUE，防止底部线或错误信号
   ArrayInitialize(filtBuffer, EMPTY_VALUE);
   ArrayInitialize(hiBandBuffer, EMPTY_VALUE);
   ArrayInitialize(loBandBuffer, EMPTY_VALUE);
   ArrayInitialize(buySignal, EMPTY_VALUE);
   ArrayInitialize(sellSignal, EMPTY_VALUE);
   ArrayInitialize(directionBuffer, EMPTY_VALUE);
   ArrayInitialize(rangeBuffer, EMPTY_VALUE);

   // 使用清晰实心箭头符号
   PlotIndexSetInteger(3, PLOT_ARROW, 233);  // ▲ BUY
   PlotIndexSetInteger(4, PLOT_ARROW, 234);  // ▼ SELL
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| OnCalculate                                                      |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
   int start = MathMax(Range_Period, prev_calculated - 1);
   if(start < Range_Period)
      start = Range_Period;

   for(int i = start; i < rates_total; i++)
   {
      // 每次循环初始化信号为空
      buySignal[i] = EMPTY_VALUE;
      sellSignal[i] = EMPTY_VALUE;

      double src = price[i];
      double rng = RangeSize(price, Range_Period, Range_Multiplier, i);
      double filt = RangeFilter(src, rng);
      double hi_band = filt + rng;
      double lo_band = filt - rng;

      filtBuffer[i] = filt;
      hiBandBuffer[i] = hi_band;
      loBandBuffer[i] = lo_band;
      rangeBuffer[i] = rng;

      // 确定方向
      double dir = 0;
      if(i > 0)
      {
         if(filt > filtBuffer[i-1]) dir = 1;
         else if(filt < filtBuffer[i-1]) dir = -1;
         else dir = directionBuffer[i-1];
      }
      directionBuffer[i] = dir;

      // 检测趋势转折
      if(i > 1)
      {
         // 下跌转上升
         if(directionBuffer[i-1] == -1 && dir == 1)
         {
            buySignal[i] = lo_band - (rng * 0.3);
            if(Enable_Alert)
               Alert(Symbol(), " 🟢 BUY @ ", DoubleToString(src, _Digits));
         }

         // 上升转下跌
         if(directionBuffer[i-1] == 1 && dir == -1)
         {
            sellSignal[i] = hi_band + (rng * 0.3);
            if(Enable_Alert)
               Alert(Symbol(), " 🔴 SELL @ ", DoubleToString(src, _Digits));
         }
      }

      // 调试输出
      if(Enable_DebugLog && (i % 100 == 0))
         PrintFormat("Bar[%d] src=%.5f filt=%.5f rng=%.5f dir=%d", i, src, filt, rng, (int)dir);
   }

   return(rates_total);
}
